home *** CD-ROM | disk | FTP | other *** search
- /* Machine or compiler-dependent portions of kernel
- * Turbo-C version for PC
- * Copyright 1991 Phil Karn, KA9Q
- */
- #include <stdio.h>
- #ifdef MSDOS
- #include <dos.h>
- #endif
- #include "global.h"
- #include "config.h"
- #include "proc.h"
- #ifndef UNIX
- #include "pc.h"
- #endif
- #include "commands.h"
- #include "socket.h"
-
- #ifndef UNIX
- static char *Taskers[] = {
- "",
- "DoubleDos",
- "DesqView",
- "Windows",
- "DOS 5/6",
- "OS/2 DOS",
- "DPMI"
- };
-
- static oldNull;
-
- /* Template for contents of jmp_buf in Turbo C */
- struct env {
- unsigned sp;
- unsigned ss;
- unsigned flag;
- unsigned cs;
- unsigned ip;
- unsigned bp;
- unsigned di;
- unsigned es;
- unsigned si;
- unsigned ds;
- };
- #endif
-
- #ifdef UNIX
- /*
- * There are several different ways to implement jmp_buf's. We use macros to
- * extract the fields. Note that these must expand into lvalues, because we
- * load them during process initialization. Current code only uses _SP and
- * _PC; this may change.
- *
- * I should fold the DOS code into this, but then I need to worry about
- * segments. No thanks.
- */
-
- #ifdef M_UNIX
- /*
- * I am unsure of these; the i386 contents are not documented in 3.2.2. I
- * guessed at them by comparing "info regs" with the contents of a jmp_buf
- * immediately after a setjmp().
- */
- #define _PC(p) (p->env[5])
- #define _SP(p) (p->env[4])
- #define _BP(p) (p->env[3])
- #endif
-
- #ifdef linux
- #define _PC(p) (p->env->__pc)
- #define _SP(p) (p->env->__sp)
- #define _BP(p) (p->env->__bp)
- #endif
-
- #endif
-
- #ifndef UNIX
- static int chkintstk __ARGS((void));
- #endif
- static int stkutil __ARGS((struct proc *pp));
-
- void
- kinit()
- {
- #ifndef UNIX
- int i;
-
- /* Initialize interrupt stack for high-water-mark checking */
- for(i=0;i<512;i++)
- Intstk[i] = STACKPAT;
-
- /* Remember location 0 pattern to detect null pointer derefs */
- oldNull = *(unsigned short *)NULL;
- #endif
- }
- /* Print process table info
- * Since things can change while ps is running, the ready proceses are
- * displayed last. This is because an interrupt can make a process ready,
- * but a ready process won't spontaneously become unready. Therefore a
- * process that changes during ps may show up twice, but this is better
- * than not having it showing up at all.
- */
- int
- ps(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct proc *pp;
- #ifndef UNIX
- register struct env *ep;
- #endif
- int i;
-
- #ifdef UNIX
- tprintf("Uptime %s",tformat(secclock()));
- #else
- tprintf("Uptime %s Stack %x max intstk %u psp %04x",tformat(secclock()),
- getss(),chkintstk(),_psp);
- if(Mtasker != 0){
- tprintf("\nRunning under %s",Taskers[Mtasker]);
- }
- #endif
- tputs("\n");
-
- #ifdef UNIX
- tprintf("PID SP stksize maxstk event fl in \
- out name\n");
-
- for (pp = Susptab; pp != NULLPROC; pp = pp->next)
- {
- if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d \
- %3d %s\n",
- FP_SEG(pp), FP_SEG(_SP(pp)), (int32) pp->stksize,
- (int32) stkutil(pp), FP_SEG(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input, pp->output, pp->name) == EOF)
- return 0;
- }
- for (i = 0; i < PHASH; i++)
- {
- for (pp = Waittab[i]; pp != NULLPROC; pp = pp->next)
- {
- if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx \
- %c%c%c %3d %3d %s\n",
- FP_SEG(pp), FP_SEG(_SP(pp)),
- (int32) pp->stksize, (int32) stkutil(pp),
- FP_SEG(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input, pp->output, pp->name) == EOF)
- return 0;
- }
- }
- for (pp = Rdytab; pp != NULLPROC; pp = pp->next)
- {
- if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx \
- %c%c%c %3d %3d %s\n",
- FP_SEG(pp), FP_SEG(_SP(pp)), (int32) pp->stksize,
- (int32) stkutil(pp), FP_SEG(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input, pp->output, pp->name) == EOF)
- return 0;
- }
- if( Curproc != NULLPROC)
- {
- if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx \
- %c%c%c %3d %3d %s\n",
- FP_SEG(Curproc), FP_SEG(_SP(Curproc)),
- (int32) Curproc->stksize, (int32) stkutil(Curproc),
- FP_SEG(Curproc->event),
- Curproc->i_state ? 'I' : ' ',
- (Curproc->state & WAITING) ? 'W' : ' ',
- (Curproc->state & SUSPEND) ? 'S' : ' ',
- Curproc->input, Curproc->output,
- Curproc->name) == EOF)
- return 0;
- }
- #else
- tputs("PID SP stksize maxstk event fl in out name\n");
-
- for(pp = Susptab;pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- if(tprintf("%4.4x %-10lx%-10u%-10u%-10lx%c%c%c %3d %3d %s\n",
- FP_SEG(pp),
- ptol(MK_FP(ep->ss,ep->sp)),
- pp->stksize,
- stkutil(pp),
- ptol(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input, pp->output,
- pp->name) == EOF)
- return 0;
- }
- for(i=0;i<PHASH;i++){
- for(pp = Waittab[i];pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- if(tprintf("%4.4x %-10lx%-10u%-10u%-10lx%c%c%c %2d %2d %s\n",
- FP_SEG(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
- ptol(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input,pp->output,
- pp->name) == EOF)
- return 0;
- }
- }
- for(pp = Rdytab;pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- if(tprintf("%4.4x %-10lx%-10u%-10u %c%c%c %2d %2d %s\n",
- FP_SEG(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input,pp->output,
- pp->name) == EOF)
- return 0;
- }
- if(Curproc != NULLPROC){
- ep = (struct env *)&Curproc->env;
- tprintf("%4.4x %-10lx%-10u%-10u %c %2d %2d %s\n",
- FP_SEG(Curproc),ptol(MK_FP(ep->ss,ep->sp)),Curproc->stksize,
- stkutil(Curproc),
- Curproc->i_state ? 'I' : ' ',
- Curproc->input,Curproc->output,
- Curproc->name);
- }
- #endif
- return 0;
- }
- static int
- stkutil(pp)
- struct proc *pp;
- {
- unsigned i;
- register int16 *sp;
-
- #ifdef UNIX
- #ifdef linux
- if (FP_SEG(pp->stack) == 0xC0000000)
- #else
- if (FP_SEG(pp->stack) == 0x80000000)
- #endif
- return pp->stksize;
- #endif
- i = pp->stksize;
- for(sp = pp->stack;*sp == STACKPAT && sp < pp->stack + pp->stksize;sp++)
- i--;
- return i;
- }
- /* Return number of used words in interrupt stack. Note hardwired value
- * for stack size; this is also found in the various .asm files
- */
- #ifndef UNIX
- static int
- chkintstk()
- {
- register int i;
- register int16 *cp;
-
- for(i=512,cp = Intstk; i != 0 && *cp == STACKPAT; cp++)
- i--;
- return i;
- }
- #endif
-
- /* Verify that stack pointer for current process is within legal limits;
- * also check that no one has dereferenced a null pointer
- */
- #ifdef UNIX
- static void
- #ifdef PROTOTYPES
- __chkstk_internal(int16 spp)
- #else
- __chkstk_internal(spp)
- int16 spp;
- #endif
- {
- int16 *sp, *sbase, *stop;
-
- sp = &spp; /* close enough for government work */
- sbase = Curproc->stack;
- if(sbase == NULL)
- return; /* Main task -- too hard to check */
- stop = sbase + Curproc->stksize;
- if(sp < sbase || sp >= stop){
- tprintf("Stack violation, process %s\n",Curproc->name);
- tprintf("SP = %lx, legal stack range [%lx,%lx)\n",
- ptol(sp),ptol(sbase),ptol(stop));
- tflush();
- rflush();
- killself();
- }
- }
- #endif
-
- void
- chkstk()
- {
- #ifdef UNIX
- __chkstk_internal(0); /* must have an argument to take address of */
- #else
- int16 *sbase;
- int16 *stop;
- int16 *sp;
- #ifdef MULTITASK
- extern int Nokeys; /* indicates we are shelled out [pc.c]*/
- #endif
-
- sp = MK_FP(_SS,_SP);
- if(_SS == _DS){
- /* Probably in interrupt context */
- return;
- }
- sbase = Curproc->stack;
- if(sbase == NULL)
- return; /* Main task -- too hard to check */
-
- stop = sbase + Curproc->stksize;
- if(sp < sbase || sp >= stop){
- printf("Stack violation, process %s\n",Curproc->name);
- printf("SP = %lx, legal stack range [%lx,%lx)\n",
- ptol(sp),ptol(sbase),ptol(stop));
- fflush(stdout);
- killself();
- }
- if(*(unsigned short *)NULL != oldNull){
- #ifdef MULTITASK
- if(!Nokeys) /* don't complain if we are shelled out */
- #endif
- printf("WARNING: Location 0 smashed, process %s\n",Curproc->name);
- *(unsigned short *)NULL = oldNull;
- fflush(stdout);
- }
- #endif
- }
- /* Machine-dependent initialization of a task */
- void
- psetup(pp,iarg,parg1,parg2,pc)
- struct proc *pp; /* Pointer to task structure */
- int iarg; /* Generic integer arg */
- void *parg1; /* Generic pointer arg #1 */
- void *parg2; /* Generic pointer arg #2 */
- void (*pc)__ARGS((int,void*,void*)); /* Initial execution address */
- {
- register int16 *stktop; /* KF8NH was "int", this breaks 32-bit code */
- #ifndef UNIX
- register struct env *ep;
- #endif
-
- /* Set up stack to make it appear as if the user's function was called
- * by killself() with the specified arguments. When the user returns,
- * killself() automatically cleans up.
- *
- * First, push args on stack in reverse order, simulating what C
- * does just before it calls a function.
- */
- stktop = (int16 *)(pp->stack + pp->stksize); /* KF8NH as above */
- #ifdef UNIX
- #ifdef LITTLE_ENDIAN
- *--stktop = (((unsigned long) parg2 & 0xFFFF0000) >> 16) & 0x0000FFFF;
- *--stktop = ((unsigned long) parg2 & 0x0000FFFF);
- *--stktop = (((unsigned long) parg1 & 0xFFFF0000) >> 16) & 0x0000FFFF;
- *--stktop = ((unsigned long) parg1 & 0x0000FFFF);
- *--stktop = (((unsigned long) iarg & 0xFFFF0000) >> 16) & 0x0000FFFF;
- *--stktop = ((unsigned long) iarg & 0x0000FFFF);
- *--stktop = (((unsigned long) killself & 0xFFFF0000) >> 16) & 0x0000FFFF;
- *--stktop = ((unsigned long) killself & 0x0000FFFF);
- #else
- *--stktop = ((unsigned long) parg2 & 0x0000FFFF);
- *--stktop = (((unsigned long) parg2 & 0xFFFF0000) >> 16) & 0x0000FFFF;
- *--stktop = ((unsigned long) parg1 & 0x0000FFFF);
- *--stktop = (((unsigned long) parg1 & 0xFFFF0000) >> 16) & 0x0000FFFF;
- *--stktop = ((unsigned long) iarg & 0x0000FFFF);
- *--stktop = (((unsigned long) iarg & 0xFFFF0000) >> 16) & 0x0000FFFF;
- *--stktop = ((unsigned long) killself & 0x0000FFFF);
- *--stktop = (((unsigned long) killself & 0xFFFF0000) >> 16) & 0x0000FFFF;
- #endif
- #else
- #ifdef LARGEDATA
- *--stktop = FP_SEG(parg2);
- #endif
- *--stktop = FP_OFF(parg2);
- #ifdef LARGEDATA
- *--stktop = FP_SEG(parg1);
- #endif
- *--stktop = FP_OFF(parg1);
- *--stktop = iarg;
-
- /* Now push the entry address of killself(), simulating the call to
- * the user function.
- */
- #ifdef LARGECODE
- *--stktop = FP_SEG(killself);
- #endif
- *--stktop = FP_OFF(killself);
- #endif
-
- /* Set up task environment. Note that for Turbo-C, the setjmp
- * sets the interrupt enable flag in the environment so that
- * interrupts will be enabled when the task runs for the first time.
- * Note that this requires newproc() to be called with interrupts
- * enabled!
- */
- setjmp(pp->env);
- #ifdef UNIX
- _SP(pp) = stktop;
- _BP(pp) = stktop;
- _PC(pp) = pc;
- #else
- ep = (struct env *)&pp->env;
- ep->ss = FP_SEG(stktop);
- ep->sp = FP_OFF(stktop);
- ep->cs = FP_SEG(pc); /* Doesn't hurt in small model */
- ep->ip = FP_OFF(pc);
- #endif
- /* Task initially runs with interrupts on */
- pp->i_state = 1;
- }
- unsigned
- #ifdef PROTOTYPES
- phash(volatile void *event)
- #else
- phash(event)
- void *event;
- #endif
- {
- register unsigned x;
-
- /* Fold the two halves of the pointer */
- #ifdef UNIX
- x = (unsigned) event;
- #else
- x = FP_SEG(event) ^ FP_OFF(event);
- #endif
-
- /* If PHASH is a power of two, this will simply mask off the
- * higher order bits
- */
- return x % PHASH;
- }
-